home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Graphics⁄Sound / RTrace-1.0-src / polygon.c < prev    next >
Text File  |  1992-08-17  |  7KB  |  212 lines

  1. /*
  2.  * Copyright (c) 1988, 1992 Antonio Costa, INESC-Norte.
  3.  * All rights reserved.
  4.  *
  5.  * This code received contributions from the following people:
  6.  *
  7.  *  Roman Kuchkuda      - basic ray tracer
  8.  *  Mark VandeWettering - MTV ray tracer
  9.  *  Augusto Sousa       - overall, shading model
  10.  *
  11.  * Redistribution and use in source and binary forms are permitted
  12.  * provided that the above copyright notice and this paragraph are
  13.  * duplicated in all such forms and that any documentation,
  14.  * advertising materials, and other materials related to such
  15.  * distribution and use acknowledge that the software was developed
  16.  * by Antonio Costa, at INESC-Norte. The name of the author and
  17.  * INESC-Norte may not be used to endorse or promote products derived
  18.  * from this software without specific prior written permission.
  19.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  20.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  21.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  22.  */
  23. #include "defs.h"
  24. #include "extern.h"
  25.  
  26. /**********************************************************************
  27.  *    RAY TRACING - Polygon - Version 7.0                             *
  28.  *                                                                    *
  29.  *    MADE BY    : Antonio Costa, INESC-Norte, October 1988           *
  30.  *    ADAPTED BY : Antonio Costa, INESC-Norte, June 1989              *
  31.  *    MODIFIED BY: Antonio Costa, INESC-Norte, March 1992             *
  32.  **********************************************************************/
  33.  
  34. /***** Polygon *****/
  35. real
  36. polygon_intersect(position, vector, object)
  37.   xyz_ptr         position, vector;
  38.   object_ptr      object;
  39. {
  40.   boolean         qi, ri, qj, rj;
  41.   REG int         cross, points, i, j, u, v;
  42.   REG real        distance, k;
  43.   real            temp[3];
  44.   polygon_ptr     polygon;
  45.  
  46.   REALINC(polygon_tests);
  47.   polygon = (polygon_ptr) object->data;
  48.   k = DOT_PRODUCT(*vector, polygon->normal);
  49.   if (ABS(k) >= ROUNDOFF)
  50.   {
  51.     distance = -(DOT_PRODUCT(*position, polygon->normal) + polygon->d) / k;
  52.     if (distance > threshold_distance)
  53.     {
  54.       cross = 0;
  55.       temp[0] = distance * vector->x + position->x;
  56.       temp[1] = distance * vector->y + position->y;
  57.       temp[2] = distance * vector->z + position->z;
  58.       points = SUCC(polygon->points);
  59.       u = polygon->u;
  60.       v = polygon->v;
  61.       for (i = 0; i <= polygon->points; POSINC(i))
  62.       {
  63.         j = SUCC(i) MOD points;
  64.         qi = FALSE;
  65.         ri = FALSE;
  66.         qj = FALSE;
  67.         rj = FALSE;
  68.         if (polygon->coords[i][v] == polygon->coords[j][v])
  69.           continue;
  70.         if (polygon->coords[i][v] < temp[v])
  71.           qi = TRUE;
  72.         if (polygon->coords[j][v] < temp[v])
  73.           qj = TRUE;
  74.         if (qi == qj)
  75.           continue;
  76.         if (polygon->coords[i][u] < temp[u])
  77.           ri = TRUE;
  78.         if (polygon->coords[j][u] < temp[u])
  79.           rj = TRUE;
  80.         if (ri AND rj)
  81.         {
  82.           POSINC(cross);
  83.           continue;
  84.         }
  85.         if ((NOT ri) AND(NOT rj))
  86.           continue;
  87.         k = (polygon->coords[j][v] - polygon->coords[i][v]) /
  88.           (polygon->coords[j][u] - polygon->coords[i][u]);
  89.         if ((temp[v] - polygon->coords[j][v] + k *
  90.              (polygon->coords[j][u] - temp[u])) / k <= threshold_distance)
  91.           POSINC(cross);
  92.       }
  93.       if (ODD(cross))
  94.         return distance;
  95.       return 0.0;
  96.     }
  97.     return 0.0;
  98.   }
  99.   return 0.0;
  100. }
  101. void
  102. polygon_normal(position, object, normal)
  103.   xyz_ptr         position;
  104.   object_ptr      object;
  105.   xyz_ptr         normal;
  106. {
  107.   polygon_ptr     polygon;
  108.  
  109.   polygon = (polygon_ptr) object->data;
  110.   STRUCT_ASSIGN(*normal, polygon->normal);
  111. }
  112. static boolean
  113. load_polygon(polygon)
  114.   polygon_ptr     polygon;
  115. {
  116.   REG real        l;
  117.   xyz_struct      p, p0;
  118.  
  119.   p.x = polygon->coords[1][0] - polygon->coords[0][0];
  120.   p.y = polygon->coords[1][1] - polygon->coords[0][1];
  121.   p.z = polygon->coords[1][2] - polygon->coords[0][2];
  122.   p0.x = polygon->coords[2][0] - polygon->coords[0][0];
  123.   p0.y = polygon->coords[2][1] - polygon->coords[0][1];
  124.   p0.z = polygon->coords[2][2] - polygon->coords[0][2];
  125.   CROSS_PRODUCT(polygon->normal, p, p0);
  126.   l = LENGTH(polygon->normal);
  127.   if (l < ROUNDOFF)
  128.     return TRUE;
  129.   polygon->normal.x /= l;
  130.   polygon->normal.y /= l;
  131.   polygon->normal.z /= l;
  132.   STRUCT_ASSIGN(p, polygon->normal);
  133.   if ((ABS(p.x) > ABS(p.y)) AND(ABS(p.x) > ABS(p.z)))
  134.   {
  135.     polygon->u = 1;
  136.     polygon->v = 2;
  137.   } else if ((ABS(p.y) > ABS(p.x)) AND(ABS(p.y) > ABS(p.z)))
  138.   {
  139.     polygon->u = 0;
  140.     polygon->v = 2;
  141.   } else
  142.   {
  143.     polygon->u = 0;
  144.     polygon->v = 1;
  145.   }
  146.   p0.x = polygon->coords[0][0];
  147.   p0.y = polygon->coords[0][1];
  148.   p0.z = polygon->coords[0][2];
  149.   polygon->d = -DOT_PRODUCT(p, p0);
  150.   return FALSE;
  151. }
  152. void
  153. polygon_enclose(object)
  154.   object_ptr      object;
  155. {
  156.   REG int         i;
  157.   xyz_struct      temp1, temp2;
  158.   polygon_ptr     polygon;
  159.  
  160.   polygon = (polygon_ptr) object->data;
  161.   if (object->transf != NULL)
  162.   {
  163.     for (i = 0; i <= polygon->points; POSINC(i))
  164.     {
  165.       temp1.x = polygon->coords[i][0];
  166.       temp1.y = polygon->coords[i][1];
  167.       temp1.z = polygon->coords[i][2];
  168.       transform(object->inv_transf, &temp1, &temp2);
  169.       polygon->coords[i][0] = temp2.x;
  170.       polygon->coords[i][1] = temp2.y;
  171.       polygon->coords[i][2] = temp2.z;
  172.     }
  173.     FREE(object->transf);
  174.     object->transf = NULL;
  175.   }
  176.   if (load_polygon(polygon))
  177.   {
  178.     WRITE(results, "Object %d is a degenerate POLYGON\n", object->id);
  179.     WRITE(results, "1st vertex COORDS: %g %g %g\n",
  180.       polygon->coords[0][0],
  181.       polygon->coords[0][1],
  182.       polygon->coords[0][2]);
  183.     WRITE(results, "2nd vertex COORDS: %g %g %g\n",
  184.       polygon->coords[1][0],
  185.       polygon->coords[1][1],
  186.       polygon->coords[1][2]);
  187.     runtime_abort("cannot process POLYGON");
  188.   }
  189.   object->min->x = INFINITY;
  190.   object->min->y = INFINITY;
  191.   object->min->z = INFINITY;
  192.   object->max->x = -INFINITY;
  193.   object->max->y = -INFINITY;
  194.   object->max->z = -INFINITY;
  195.   for (i = 0; i <= polygon->points; POSINC(i))
  196.   {
  197.     object->max->x = MAX(object->max->x, polygon->coords[i][0]);
  198.     object->max->y = MAX(object->max->y, polygon->coords[i][1]);
  199.     object->max->z = MAX(object->max->z, polygon->coords[i][2]);
  200.     object->min->x = MIN(object->min->x, polygon->coords[i][0]);
  201.     object->min->y = MIN(object->min->y, polygon->coords[i][1]);
  202.     object->min->z = MIN(object->min->z, polygon->coords[i][2]);
  203.   }
  204.   /* Adjust dimensions */
  205.   object->max->x += threshold_distance;
  206.   object->max->y += threshold_distance;
  207.   object->max->z += threshold_distance;
  208.   object->min->x -= threshold_distance;
  209.   object->min->y -= threshold_distance;
  210.   object->min->z -= threshold_distance;
  211. }
  212.